package cn.com.ylpw.web.order.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.com.ylpw.spring.SpringController;
import cn.com.ylpw.sso.client.AutoLoginController;
import cn.com.ylpw.utils.StringUtils;
import cn.com.ylpw.web.common.controller.CommonController;
import cn.com.ylpw.web.enums.OrderInfo.OrderResult;
import cn.com.ylpw.web.order.service.OrderService;
import cn.com.ylpw.web.order.service.payService;
import cn.com.ylpw.web.product.service.IProductService;
import cn.com.ylpw.web.util.DateUtils;
import cn.com.ylpw.web.util.MD5;
import cn.com.ylpw.web.util.OrderUtils;
import cn.com.ylpw.web.util.ServletUtil;
import cn.com.ylpw.web.util.StringUtil;

/**
 * 支付Controller
 * 
 * @author 于旺
 * @date   2015年9月23日13:56:31
 * @Copyright ©2003-2015 北京春秋永乐文化传播有限公司. All Rights Reserved.
 * @version 新架构 1.0
 */
@Controller("payController")
@RequestMapping("/payNew")
public class PayController extends SpringController{
	
	public final Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	@Qualifier("payService")
	private payService payService;
	@Autowired
	@Qualifier("orderService")
	private OrderService orderService;
	@Autowired
	@Qualifier("productService")
	private IProductService productService;
	@Autowired
	@Qualifier("autoLoginController")
	private AutoLoginController autoLoginController;
	/**
	 * 立即购买跳转订单确认详情页面
	 * 
	 * @author 于旺
	 * @date   2015年9月23日17:36:55
	 * @param  params
	 * @return ModelAndView
	 */
	@RequestMapping("/toPay")
	public ModelAndView toPay(HttpServletRequest request, HttpServletResponse response,HttpSession session ,@RequestParam Map<String,Object> params) {
		ModelAndView mv = new ModelAndView();
		String orderId = params.get("orderId").toString();
		if (StringUtils.isEmpty(orderId)) {
			return CommonController.forwardError(OrderResult.订单号不存在);
		}
		//判断用户是否已经登录
		Map<String, Object> customer = ServletUtil.getCustomer(session);
		if (customer == null || customer.size() == 0) {
			return autoLoginController.redirect(request,OrderUtils.getFullURL(request));
		}
		mv.addObject("onlinetime", null);
		mv.addObject("paylimittime", null);
		
		params.put("customersid", ServletUtil.getCustomerId(session));
		List<Map<String, Object>> orderspayList = payService.findOrderPayById(params);
		if(orderspayList==null || orderspayList.size()==0){
			return CommonController.forwardError(OrderResult.商品支付信息查询异常);
		}
		//多商品不拆单的显示
		String names = "";
		for (int i = 0; i < orderspayList.size(); i++) {
			names +="<p>"+orderspayList.get(i).get("NAMES")+"</p>";
		}
		mv.addObject("names",names);
		Map<String, Object> orderspay = orderspayList.get(0);
		mv.addObject("orderspay",orderspay);
		Integer isPayFlag = 1; //商品是否可以支付 0不可以 1为可以
		//订单支付状态
		int paystatus = NumberUtils.toInt(orderspay.get("PAYSTATUS").toString(), -1);
		if (2 == paystatus) {
			//0元直接支付成功跳转成功页面
			return CommonController.forwardError(OrderResult.该订单已经支付成功);
		}
		
		/**
		 * 验证是否允许支付
		 */
		Map<String,Object> ckPay = this.checkPay(params);
		if(!Boolean.parseBoolean(ckPay.get("success").toString())) {
			log.warn("商品已经不能支付{}",params);
			isPayFlag = 0;
			return CommonController.forwardErrorMsg(1);//包含不可售票价
		}
		

		//TODO 判断演出时间是否过期
		SimpleDateFormat formatter = new SimpleDateFormat(DateUtils.DAY_FROMAT);      
		Date rightDate = new Date();                         //获取当前时间      
		String nowDate = formatter.format(rightDate);        //格式化时间
		List<Map<String, Object>> orderdetailList = null;
		try {
			orderdetailList = orderService.findOrderdetailsByOrderIdNew(params);
		} catch (Exception e) {
			log.error("查询订单明细失败:{}",params,e);
		}
		for(Map <String, Object> orderdetail : orderdetailList){
			Integer productplayId = Integer.valueOf(orderdetail.get("productplayId").toString());
			params.put("productplayId", productplayId);
			Map<String, Object> productplay = null;
			try {
				productplay = productService.findByProductPlayId(params);
			} catch (Exception e) {
				log.error("查询票价明细失败:{}",params,e);
			}
			String playDate = productplay.get("playDate") == null ? null : productplay.get("playDate").toString();
			String playdate = "";
			if(null == playDate){
				playDate = productplay.get("time").toString();
				playdate = playDate;
				String [] times = playDate.split("-");
				playDate = "";
				if(times.length <= 4){
					for(int i=0; i < 3; i++){
						if(StringUtil.isEmpty(playDate)){
							playDate = times[i];
						}else{
							playDate = playDate + "-" + times[i];
						}
					}
				}else{
					for(int i=3; i < 6; i++){
						if(StringUtil.isEmpty(playDate)){
							playDate = times[i];
						}else{
							playDate = playDate + "-" + times[i];
						}
					}
				}
				productplay.put("playDate", DateUtils.parseDate(playDate, DateUtils.DAY_FROMAT));
				productplay.put("time", times[times.length-1]);
			}
			if(!StringUtil.isEmpty(playdate)){
				productplay.put("playDate", null);
				productplay.put("time", playdate);
			}
			String playtime=null;
			//TODO 增加判断 null!=productplay.get("playDate") 特殊票价playdate为空,但time里的值非规则24小时格式,进入第一个判断会报错...  T.L 20140801
			if(productplay.get("time")!=null && null!=productplay.get("playDate")){
				playtime=playDate.substring(0, 10)+" "+productplay.get("time")+":00";
			}else{
				playtime=playDate.substring(0, 10)+" "+"18:00:00";
			}
			
			try{
				if(rightDate.after(DateUtils.parseDateLong(playtime))){
					log.warn("去支付订单--客户购买的商品已经演出结束！");
					isPayFlag = 0;
				}
			}catch(Exception e){
				String play=playtime.substring(0,11);
				SimpleDateFormat formatters = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
				Date nowtime=new Date();
				String now=formatter.format(nowtime);
				if(DateUtils.getDiffDays(now,play)<0){
					log.warn("去支付订单--客户购买的商品已经演出结束！");
					isPayFlag = 0;
				}
			}
			if(Integer.parseInt(productplay.get("num").toString())<0 && Integer.parseInt(productplay.get("num").toString())!= -1){
				log.warn("去支付订单--客户购买的商品库存不足！");
				isPayFlag = 0;
			}
			
		}
		String productId = orderspay.get("PIDS").toString();
		params.put("productId", productId);
		// 判断订单是否是选座和抢座
				int type = NumberUtils.toInt(orderspay.get("TYPE").toString(), -1);
				// 是否为抢座 [1 是 0 否] 
				int isrobseat = NumberUtils.toInt(orderspay.get("ISROBSEAT").toString(), -1);
				
				boolean isFlag = false;
				
				if (type == 1 || type == 20) {
					// 抢座流程
					Map<String, Object> spqp = null;
					try {
						spqp = productService.findRobseatProductById(params);
					} catch (Exception e) {
						log.warn("抢座信息查询失败:{}",params,e);
					}
					if (null != spqp && null != spqp.get("qzbdate")){
						Date qzBeginDate = DateUtils.dateOfAny(spqp.get("qzbdate").toString());//抢座开始时间
						Date qzEndDate = DateUtils.dateOfAny(spqp.get("qzedate").toString());//抢座结束时间
						Date nowdate = new Date();
						//【当前时间大于抢座开始时间】 并且【当前时间小于抢座结束时间】 
						if(nowdate.before(qzBeginDate) && nowdate.after(qzEndDate)){
							isFlag = true;
							isPayFlag = 0;
						}
					}
				}
		Map<String, Object> orders = null;
		try {
			orders = orderService.findOrderById(params);
		} catch (Exception e) {
			log.error("根据ID查询订单失败:{}",params,e);
		}
		List<Map<String, Object>> product = null;
		//手机端票价支付限时 只支持立即购买
		try {
			product = productService.getProductByIds(params);
		} catch (Exception e) {
			log.error("查询商品信息失败:{}",params,e);
		}
		if (product == null) {
			return CommonController.forwardError(OrderResult.商品信息异常);
		}
		//拼接商品信息
		String productNames = "";
		for (int i = 0; i < product.size(); i++) {
			
			if (i==product.size()-1) {
				productNames += product.get(i).get("name");
			}else {
				productNames += product.get(i).get("name")+",";
			}
		}
		//过滤掉双引号和单引号，防止form中无法传值
		mv.addObject("productNames",productNames.replace("\"", "").replace("\'", ""));
		//只取支付限时最短的商品，空值放最后
		Map<String, Object> productObj = product.get(0);
		//[未支付、部分支付]的才能支付
		if (0 == paystatus || 1 == paystatus) {
			int isonlineseat = NumberUtils.toInt(orderspay.get("TYPE").toString());		//【订单类型】0:普通,1:选座,20:抢座
			mv.addObject("customer", customer);									//用户实体
			mv.addObject("dztype",orders.get("dzType"));
			params.put("productId", orderspay.get("PRODUCTID").toString().split(",")[0]);
				// 设置支付时间pay_limit_time,新增订单状态为：已处理(starus=9)的，支付限时取消
				if(productObj.get("pay_time_limit") != null  && !productObj.get("pay_time_limit").toString().equals("0")&& !"9".equals(orderspay.get("STARUS").toString())  ){
					long currentTime = System.currentTimeMillis();
					Date onlinetime = DateUtils.getDateAddMinutes(DateUtils.dateOfAny((orderspay.get("CREATETIME").toString())), Integer.parseInt(productObj.get("pay_time_limit").toString()));
					String onlinetimeString = DateUtils.formatDate(onlinetime, DateUtils.JAVASCRIPT_FORMAT);;
					// 已等待时长 
					String paylimete = productObj.get("pay_time_limit").toString();
					mv.addObject("paylimittime", productObj.get("pay_time_limit"));
					long alreadyTime = currentTime - onlinetime.getTime();
					mv.addObject("onlinetime", isFlag ? null : onlinetimeString);
					session.setAttribute("socket_orderid", orderspay.get("ORDERSID"));
					if(alreadyTime > 1 * 60 * 1000){	// 支付时间已超时，拒绝进行支付页  5分钟
						log.warn("支付时间已超时，拒绝进行支付页");
						isPayFlag = 0;
					}
					// 倒计时计算结束--
			}
			/*抢座，选座商品控制支付时间 15分钟*/
			if (1 == isrobseat || 1 == isonlineseat || 20 == isonlineseat ||(orders.get("dzType")!=null && orders.get("dzType").toString().equals("30"))) {
				// 倒计时计算--
				long currentTime = System.currentTimeMillis();
				Date onlinetime = DateUtils.getDateAddMinutes(DateUtils.dateOfAny((orderspay.get("CREATETIME").toString())), 15);
				String onlinetimeString = DateUtils.formatDate(onlinetime, DateUtils.JAVASCRIPT_FORMAT);
				
				// 已等待时长 
				long alreadyTime = currentTime - onlinetime.getTime();
				mv.addObject("onlinetime", isFlag ? null : onlinetimeString);
				session.setAttribute("socket_orderid", orderspay.get("ORDERSID"));

				if(alreadyTime > 1 * 60 * 1000){	// 支付时间已超时，拒绝进行支付页  5分钟
					log.warn("支付超时");
					isPayFlag = 0;
				}
				// 倒计时计算结束--
			}
			
		}
		mv.addObject("product",productObj);
		Map<String, Object> payParams = new HashMap<>(); //支付列表需要的参数
		payParams.put("branch_name", productObj.get("csjx"));
		payParams.put("channel_code", "web");
		payParams.put("order_list", orderspay.get("PRODUCTPLAYIDS"));
		Map<String, Object> payMap = payService.getpayInfoMap(payParams);
		List<Map<String, Object>> cyberBankList = (List<Map<String, Object>>) payMap.get("cyberBank");
		List<Map<String, Object>> thirdPayList = (List<Map<String, Object>>) payMap.get("platForm");
		List<Map<String, Object>> othersList = (List<Map<String, Object>>) payMap.get("others");
		mv.addObject("cyberBankList",cyberBankList);
		mv.addObject("thirdPayList",thirdPayList);
		mv.addObject("othersList",othersList);
		mv.addObject("isPayFlag",isPayFlag);
		String nowDateStr = DateUtils.formatDate(new Date(),DateUtils.JAVASCRIPT_FORMAT);
		mv.addObject("nowDate",nowDateStr);
		mv.setViewName("pay/toPay");
		return mv;
	}
	
	/**
	 * 验证是否允许支付
	 * @author 于旺
	 * @createTime 2015年11月2日13:44:00
	 * @param orderId
	 * @return
	 */
	private Map<String,Object> checkPay(Map<String,Object> params) {
		Map<String,Object> msg = new HashMap<>();
		msg.put("success", true);
		msg.put("msg", "");
		try{
			List<Map<String,Object>> _list = payService.findOrderPublicPayStatus(params);
			if(_list == null || _list.size() <= 0) {
				msg.put("success", false);
				msg.put("msg", "没有找到商品");
			}
			for(Map<String,Object> status : _list) {
				// 判断票价状态1:可售、2:售完、4:预售
				if(!(Arrays.asList(new String[]{"1","2","4"}).contains(status.get("priceStarus").toString())
					// 商品状态判断0:售票中、1:预售、4:售完
					&& Arrays.asList(new String[]{"0","1","4"}).contains(status.get("tpStatus").toString())	
					// 订单状态1:未审核、9:已处理
					&& Arrays.asList(new String[]{"1","9"}).contains(status.get("orderStarus").toString())	
					// 订单支付状态0:未支付、1:部分支付
					&& Arrays.asList(new String[]{"0","1"}).contains(status.get("payStatus").toString())		
					)
					|| (Integer.parseInt(status.get("priceNum").toString())<0 && status.get("priceStarus").toString().equals("2"))
					 // 非货到付款
					|| (!StringUtil.isEmpty(status.get("discount")) && status.get("discount").toString().equals("货到付款"))
						){
					log.warn("此订单状态不允许支付{}",_list);
					msg.put("success", false);
					msg.put("msg", "此订单信息已变更，不能支付！");
				}
			}
			Map<String,Object>  orders = orderService.findOrderById(params);
			
			//BUG #5335::已修改折扣但未通过审核的订单，前台不应该能成功支付
			if(orders != null && orders.get("isDiscountReset")!=null ){
				if(orders.get("isDiscountReset").toString().equals("0") && orders.get("starus").equals("1")){
					msg.put("success", false);
					msg.put("msg", "暂时不能支付，请稍候再试或拨打服务热线：4006-228-228。");
				}
			}
			//BUG #5335 END
		}catch (Exception e) {
			log.error("订单支付状态判断异常");
			msg.put("success", false);
			msg.put("msg", "没有找到商品");
		}
		return msg;
	}
	@RequestMapping("/weiXinPay")
	public ModelAndView weiXinPay(HttpServletRequest request, HttpServletResponse response,HttpSession session ,@RequestParam Map<String,Object> params) {
		ModelAndView mv = new ModelAndView();
		String orderId = StringUtil.getString(params.get("out_order_no"));
		String weixinPayImg = "";
		//订单金额
		String total_fee = StringUtil.getString(params.get("total_fee"));
		//组装请求微信的url
		String qrcode = StringUtil.getString(params.get("qrcode"));
		String out_order_no = StringUtil.getString(params.get("out_order_no"));
		//String bank = StringUtil.getString(params.get("bank"));
		String body = StringUtil.getString(params.get("body"));
		String branch_name = StringUtil.getString(params.get("branch_name"));
		String channel_code = StringUtil.getString(params.get("channel_code"));
		String create_time = StringUtil.getString(params.get("create_time"));
		String error_url = StringUtil.getString(params.get("error_url"));
		String expire_time = StringUtil.getString(params.get("expire_time"));
		String payment_id = StringUtil.getString(params.get("payment_id"));
		String return_url = StringUtil.getString(params.get("return_url"));
		String show_url = StringUtil.getString(params.get("show_url"));
		String subject = StringUtil.getString(params.get("subject"));
		String yfb_pay_code = StringUtil.getString(params.get("yfb_pay_code"));
		String sign = this.createSign(payment_id, branch_name, channel_code,
				yfb_pay_code, return_url, out_order_no, 
				subject, body, show_url, total_fee, expire_time, 
				create_time, error_url,"","");
		weixinPayImg = qrcode+"?out_order_no="+out_order_no+"&body="+body+"&branch_name="+branch_name+"&channel_code="+channel_code
				+"&create_time="+create_time+"&error_url="+error_url+"&expire_time="+expire_time
				+"&payment_id="+payment_id+"&return_url="+return_url+"&show_url="+show_url
				+"&subject="+subject+"&yfb_pay_code="+yfb_pay_code+"&total_fee="+total_fee+"&sign="+sign;
		if (StringUtil.isEmpty(orderId)) {
			return CommonController.forwardError(OrderResult.订单号不存在);
		}
		if (StringUtil.isEmpty(weixinPayImg)) {
			return CommonController.forwardError(OrderResult.参数有误);
		}
		
		
		params.put("orderId", orderId);
		params.put("customersid", ServletUtil.getCustomerId(session));
		List<Map<String, Object>> orderspayList = new ArrayList<Map<String, Object>>();
		try {
			orderspayList = payService.findOrderPayById(params);
		} catch (Exception e) {
			return CommonController.forwardError(OrderResult.商品支付信息查询异常);
		}
		if(orderspayList==null || orderspayList.size()==0){
			return CommonController.forwardError(OrderResult.商品支付信息查询异常);
		}
		//多商品不拆单的显示
		String productName = "";
		for (int i = 0; i < orderspayList.size(); i++) {
			productName += orderspayList.get(i).get("CITYNAME").toString().replace("市", "")+"-"+orderspayList.get(i).get("NAMES").toString();
		}
		Map<String, Object> orderspay = orderspayList.get(0);
		mv.addObject("orderId",orderId);
		mv.addObject("weixinPayImg",weixinPayImg);
		mv.addObject("total_fee",total_fee);
		mv.addObject("productName",productName);
		mv.addObject("orderspay",orderspay);
		mv.setViewName("pay/weiXinPay");
		return mv;
	}
	
	/**
	 * 
	 * @description  功能描述:创建去支付平台的加密串
	 * @author 	              作       者: 于旺
	 * @param        参       数: 提交到支付平台的所有参数
	 * @return       返回类型: String 
	 * @createdate   建立日期: 2015年11月25日12:32:58
	 */
	@RequestMapping(value = "/createSign",method = RequestMethod.POST)
	public @ResponseBody String createSign(String payment_id,String branch_name,String channel_code,String yfb_pay_code,
			String return_url,String out_order_no,String subject,String body,
			String show_url,String total_fee,String expire_time,String create_time,String error_url,String bank_cardno,String verifyCode){
		String sign = "";
		Map<String, String> signMap = new HashMap<>(); //加密参数map
		signMap.put("payment_id",payment_id);
		signMap.put("branch_name",branch_name);
		signMap.put("channel_code",channel_code);
		signMap.put("yfb_pay_code",yfb_pay_code);
		signMap.put("return_url",return_url);
		signMap.put("out_order_no",out_order_no);
		signMap.put("subject",subject);
		signMap.put("body",body);
		signMap.put("show_url",show_url);
		signMap.put("total_fee",total_fee);
		signMap.put("expire_time",expire_time);
		signMap.put("create_time",create_time);
		signMap.put("error_url",error_url);
		//小浦支付活动
		if (!StringUtil.isEmpty(bank_cardno)) {
			signMap.put("bank_cardno",bank_cardno);
		}
		if (!StringUtil.isEmpty(verifyCode)) {
			signMap.put("verifyCode",verifyCode);
		}
		sign = this.createKey(signMap,"");
		return sign;
	}		
	public String createKey(Map<String, String> params, String charset) {
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		StringBuffer sbf = new StringBuffer();
		int ck = 0;
		try {
			for (String key : keys) {
				if (StringUtils.isNotBlank(params.get(key))) {
					sbf.append(key);
					sbf.append("=");
					if (StringUtils.isNotBlank(charset)) {
						sbf.append(URLEncoder.encode(params.get(key).toString(), charset));
					} else {
						sbf.append(params.get(key).toString());
					}
				}
				if (ck < params.keySet().size() - 1) {
					sbf.append("&");
				}
				ck++;
			}
		} catch (UnsupportedEncodingException e) {
			log.error("支付KEY处理失败:{}",params,e);
		}
		return  MD5.sign((sbf.toString() + "192e4fr61ui8090o"), "utf-8");
	}
	
	
}
